home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / mac_gdiff 1.51 / gdiff-mac1.src.1.15 / mac_support.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-18  |  9.0 KB  |  441 lines  |  [TEXT/????]

  1. /*
  2.  * fake routines for the macintosh gnu support
  3.  * Written by Aaron Wohl (aw0g+@andrew.cmu.edu)
  4.  * Public domain
  5.  */
  6.  
  7. #include <sys/stat.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <console.h>
  11. #include <unix.h>
  12. #include <fcntl.h>
  13. #include <sys/dir.h>
  14. #include <errno.h>
  15. #include <string.h>
  16.  
  17. /*
  18.  * calls that gnu diff refrences but which we don't implement
  19.  */
  20. #define BOGUS(xx_rtn) void xx_rtn() {fprintf(stderr,"unimplemented call to %s",#xx_rtn);exit(1);}
  21.  
  22. BOGUS(dup2)
  23. BOGUS(pipe)
  24. BOGUS(vfork)
  25. BOGUS(wait)
  26. BOGUS(fstat)
  27.  
  28. static int silent_quit=FALSE;    /*if true exit if no error*/
  29.  
  30. /*
  31.  * at startup remember default volume
  32.  */
  33. struct {
  34.     short vnum;
  35.     unsigned char vname[256];
  36. }ms;
  37.  
  38. /*
  39.  * cache current volume
  40.  */
  41. void remember_volume()
  42. {
  43.     if(GetVol(ms.vname,&ms.vnum)!=0) {
  44.         fprintf(stderr,"can't get current volume");
  45.         exit(1);
  46.     }
  47. }
  48.  
  49. /*
  50.  * cut off a trailing end of line
  51.  */
  52. static void chop(s)
  53. char *s;
  54. {
  55.     s=strchr(s,'\n');
  56.     if(s!=0)
  57.         *s=0;
  58. }
  59.  
  60. /*
  61.  * read the next character from input string
  62.  * update input, stop end end of input and
  63.  * keep returning 0
  64.  */
  65. static char parse_getch(char **s)
  66. {
  67.     char ch;
  68.     if(s==0)return 0;
  69.     if(*s==0)return 0;
  70.     if(**s==0)return 0;
  71.     ch=*((*s)++);
  72.     if(ch=='\t')
  73.         ch=' ';
  74.     return ch;
  75. }
  76.  
  77. /*
  78.  * break a command line up into tokens
  79.  */
  80. static int parse_command(char ***argv,char *in)
  81. {
  82. #define MAX_ARGS (30)
  83.     char ch;
  84.     int result=0;
  85.     char *out=in;
  86.     static char *real_argv[MAX_ARGS+1];
  87.     *argv= real_argv;        /*set result string pointer*/
  88.     while((ch=parse_getch(&in))!=0) {
  89.         char quote_ch=' ';            /*fields break on spaces by default*/
  90.         if(ch==' ')continue;    /*skip spaces between tokens*/
  91.         real_argv[result++]=out; /*point to start of next field*/
  92.         if(result>=MAX_ARGS) {
  93.             fprintf(stderr,"too many input fields in command line");
  94.             exit(1);
  95.         }
  96.         /*handle quoted strings*/
  97.         if((ch=='"')||(ch=='\'')) {
  98.             quote_ch=ch;
  99.             ch=parse_getch(&in);
  100.         }
  101.         while((ch!=0)&&(ch!=quote_ch)) {
  102.             *out++=ch;
  103.             ch=parse_getch(&in);
  104.         }
  105.         *out++=0;
  106.     }
  107.     return result;
  108. }
  109.  
  110. /*
  111.  * get the first finder file if it exists
  112.  */
  113. static int read_1_finder_file(AppFile *afile)
  114. {
  115.     short doWhat;
  116.     short fileCnt;
  117.     int i;
  118.     CountAppFiles(&doWhat,&fileCnt);
  119.     if(fileCnt<1)return FALSE;        /*nothing to do*/
  120.     GetAppFiles(1,afile);
  121.     for(i=0;i<fileCnt;i++)
  122.         ClrAppFiles(i);
  123.     return TRUE;
  124. }
  125.  
  126. /*
  127.  * return volume name and directory number for a working directory
  128.  */
  129. static void get_voldir(short vnum,unsigned char *vname,long *dir_id)
  130. {
  131.     WDPBRec paramBlock;
  132.     int iErr;
  133.     memset(¶mBlock,0,sizeof(paramBlock));
  134.     paramBlock.ioWDIndex=0;
  135.     paramBlock.ioVRefNum=vnum;
  136.     paramBlock.ioNamePtr=vname;
  137.     paramBlock.ioWDVRefNum=vnum;
  138.     iErr=PBGetWDInfoSync(¶mBlock);
  139.     if(iErr!=0) {
  140.         fprintf(stderr,"error reading finder working directory info %d\n",iErr);
  141.         exit(1);
  142.     }
  143.     *dir_id=paramBlock.ioWDDirID;
  144. }
  145.  
  146. #define ROOT_DIR (2L)
  147. #define MAXPATHLEN (2000)
  148.  
  149. /*
  150.  * prepend ins to outs
  151.  */
  152. char *str_prepend(char *outs,char *ins,int len)
  153. {
  154.     ins+=len-1;
  155.     while(len-- >0)
  156.         *--outs= *ins--;
  157.     return outs;
  158. }
  159.  
  160. /*
  161.  * given a volume name return it's number
  162.  */
  163. static int vol_name_to_vnum(unsigned char *vname)
  164. {
  165.     int iErr;
  166.     ParamBlockRec paramBlock;
  167.     paramBlock.volumeParam.ioVolIndex= -1;    /*lookup byname*/
  168.     paramBlock.volumeParam.ioNamePtr=vname;
  169.     iErr = PBGetVInfoSync(¶mBlock);
  170.     if(iErr!=0) {
  171.         fprintf(stderr,"error reading finder file volume info %d\n",iErr);
  172.         exit(1);
  173.     }
  174.     return paramBlock.volumeParam.ioVRefNum;
  175. }
  176.  
  177. /*
  178.  * convert mac finder info to a unix happy file name
  179.  */
  180. static void AppFile_to_fname(AppFile *afile,char *fname)
  181. {
  182.     unsigned char vol_name[32];
  183.     long dir_id;
  184.     char result[MAXPATHLEN];
  185.     char *out=result+MAXPATHLEN-1;
  186.     int vnum;
  187.     *out=0;
  188.     get_voldir(afile->vRefNum,(unsigned char *)vol_name,&dir_id);
  189. printf("orig volname '%#s'",vol_name);
  190.     if(vol_name[vol_name[0]]!=':') {
  191.         vol_name[0]++;
  192.         vol_name[vol_name[0]]=':';
  193. printf("colonized volname '%#s'",vol_name);
  194.     }
  195.     vnum=vol_name_to_vnum((unsigned char*)vol_name);
  196.     out=str_prepend(out,(char *)(afile->fName+1),afile->fName[0]);
  197.     
  198.     /*
  199.      * work up the directory tree till we get to the root directory
  200.      */
  201.     while(dir_id!=ROOT_DIR) {
  202.         CInfoPBRec pb;
  203.         int iErr;
  204.         unsigned char pfname[256];
  205.         pfname[0]=0;
  206.         memset(&pb,0,sizeof(pb));
  207.         pb.hFileInfo.ioNamePtr=pfname;
  208.         pb.hFileInfo.ioVRefNum=vnum;
  209.         pb.hFileInfo.ioDirID=dir_id;
  210.         pb.hFileInfo.ioFDirIndex= -1;    /*ask about the file itself*/
  211.         iErr = PBGetCatInfoSync(&pb);
  212.         if(iErr!=0) {
  213.             fprintf(stderr,"can't open input file supplied by the finder\n");
  214.             exit(1);
  215.         }
  216.         if((*out)!=0)
  217.             *--out=':';
  218.         out=str_prepend(out,(char*)(pfname+1),pfname[0]);
  219.         dir_id=pb.hFileInfo.ioFlParID;
  220.     }
  221.     if((*out)!=':')
  222.         *--out=':';
  223.     out=str_prepend(out,(char *)(vol_name+1),vol_name[0]);
  224.     strcpy(fname,out);
  225. }
  226.  
  227. /*
  228.  * read in the input file and return it as a string
  229.  * or nil if it does not exist
  230.  */
  231. static char *slurp_input(void)
  232. {
  233.     AppFile fileStuff;
  234.     char fname[MAXPATHLEN];
  235.     struct stat st;
  236.     char *result;
  237.     FILE *infile;
  238.     long in_buf_size;
  239.     if(!read_1_finder_file(&fileStuff))
  240.         return 0;
  241.     AppFile_to_fname(&fileStuff,fname);
  242.     printf("reading command line from '%s'\n",fname);
  243.     if(stat(fname,&st)!=0) {
  244.         fprintf(stderr,"can't get size of input file '%s'",fname);
  245.         exit(1);
  246.     }
  247.     in_buf_size=st.st_size+1;
  248.     if((result=malloc(in_buf_size))==0) {
  249.         fprintf(stderr,"out of memory reading finder input file");
  250.         exit(1);
  251.     }
  252.     if((infile=fopen(fname,"r"))==0)  {
  253.         fprintf(stderr,"error opening finder input file errno=%d",errno);
  254.         exit(1);
  255.     }
  256.     if(fread(result,1,st.st_size,infile)!=st.st_size) {
  257.         fprintf(stderr,"error reading finder input file");
  258.         exit(1);
  259.     }
  260.     if(fclose(infile)!=0) {
  261.         fprintf(stderr,"error closing finder input file");
  262.         exit(1);
  263.     }
  264.     *(result+st.st_size)=0;
  265.     return result;
  266. }
  267.  
  268. /*
  269.  * pick off output file redirect if there is one
  270.  */
  271. void get_output_file(char *redirect)
  272. {
  273.     int echo_also=TRUE;
  274.     if(*redirect=='+') {
  275.         redirect++;
  276.         echo_also=FALSE;
  277.         printf("echo to console disabled\n");
  278.     }
  279.     if(*redirect=='!') {
  280.         redirect++;
  281.         silent_quit=TRUE;
  282.         printf("silent quit enabled\n");
  283.     }
  284.     while(*redirect==' ')
  285.         redirect++;
  286.     fprintf(stdout,"output to '%s'\n",redirect);
  287.     fflush(stdout);
  288.     if(echo_also)
  289.         cecho2file(redirect,0,stdout);
  290.     else
  291.         if(freopen(redirect,"w",stdout)==0) {
  292.             fprintf(stderr,"error opening log file errno=%d",errno);
  293.             exit(1);
  294.         }
  295. }
  296.  
  297. /*
  298.  * see if we where opened with an input file from the finder
  299.  */
  300. int finder_command(char ***argv)
  301. {
  302.     char *input=slurp_input();
  303.     char *redirect;
  304.     int result;
  305.     if(input==0)
  306.         return -1;        /*no input file to read*/
  307.     chop(input);
  308.     fprintf(stdout,"command '%s'\n",input);
  309.     fflush(stdout);
  310.     redirect=strrchr(input,'>');
  311.     if(redirect!=0)
  312.         *redirect++=0;
  313.     result=parse_command(argv,input);
  314.     if(redirect!=0)
  315.         get_output_file(redirect);
  316.     return result;
  317. }
  318.  
  319. int main(int argc,char **argv)
  320. {    
  321.     extern char *version_string;
  322.     int rc;
  323.     _fmode=O_TEXT;
  324.     remember_volume();
  325.     printf("gnu diff %s %s %s\n",version_string,__DATE__,__TIME__);
  326.     printf("mac port by Aaron Wohl (aw0g+@andrew.cmu.edu)\n");
  327.     if((argc=finder_command(&argv))<0)
  328.         argc=ccommand(&argv);
  329.     if(silent_quit)
  330.         console_options.pause_atexit=FALSE;
  331.     rc=gdiff_main(argc,argv);
  332.     fprintf(stdout,"exit code=%d\n",rc);
  333.     fflush(stdout);
  334.     exit(rc);
  335. }
  336.  
  337. /*
  338.  * get info about a file
  339.  */
  340. int stat(char *fname,struct stat *st)
  341. {
  342.     unsigned char pfname[256];
  343.     CInfoPBRec pb;
  344.     int iErr;
  345.     strcpy((char*)(pfname+1),fname);
  346.     pfname[0]=strlen(fname);
  347.     memset(&pb,0,sizeof(pb));
  348.     pb.hFileInfo.ioNamePtr=pfname;
  349.     pb.hFileInfo.ioVRefNum=ms.vnum;
  350.     iErr = PBGetCatInfo(&pb,FALSE);
  351.     if(iErr!=0) {
  352.         errno=ENOENT;
  353.         return errno;
  354.     }
  355.     st->st_size=pb.hFileInfo.ioFlLgLen;
  356.     st->st_dev=pb.hFileInfo.ioVRefNum;
  357.     st->st_ino=pb.hFileInfo.ioDirID;
  358.     st->st_mtime=pb.hFileInfo.ioFlCrDat;
  359.     if(pb.hFileInfo.ioFlAttrib&16)
  360.         st->st_mode=S_IFDIR;
  361.     else
  362.         st->st_mode=S_IFREG;
  363.     return 0;
  364. }
  365.  
  366. /*
  367.  * find the volume for this file
  368.  */
  369. static int pick_vnum(char *fname)
  370. {
  371.     unsigned char vname[256];
  372.     char *s=strchr(fname,':');
  373.     long vol_len;
  374.     if((s==0)||(s==fname))    /*if subdir or no disk use default*/
  375.         return ms.vnum;
  376.     vol_len=(s-fname)+1;
  377.     memcpy(vname+1,fname,vol_len);
  378.     vname[0]=vol_len;
  379.     return vol_name_to_vnum(vname);
  380. }
  381.  
  382. /*
  383.  * open a directory file
  384.  */
  385. DIR_pt opendir(char *fname)
  386. {
  387.     unsigned char pfname[256];
  388.     CInfoPBRec pb;
  389.     int iErr;
  390.     DIR_pt result;
  391.     strcpy((char *)(pfname+1),fname);
  392.     pfname[0]=strlen(fname);
  393.     memset(&pb,0,sizeof(pb));
  394.     pb.hFileInfo.ioNamePtr=pfname;
  395.     pb.hFileInfo.ioVRefNum=0;
  396.     iErr = PBGetCatInfo(&pb,FALSE);
  397.     if(iErr!=0) {
  398.         errno=ENOENT;
  399.         return 0L;
  400.     }
  401.     result=malloc(sizeof(*result));
  402.     result->vnum=pick_vnum(fname);
  403.     result->dirid=pb.hFileInfo.ioDirID;
  404.     result->voffset=1;
  405.     return result;
  406. }
  407.  
  408. /*
  409.  * open a directory file
  410.  */
  411. direct_pt readdir(DIR_pt adir)
  412. {
  413.     CInfoPBRec cinfo;
  414.     int os;
  415.     memset(&cinfo,0,sizeof(cinfo));
  416.     adir->dr.d_name[0]=0;
  417.     cinfo.hFileInfo.ioVRefNum=adir->vnum;
  418.     cinfo.hFileInfo.ioNamePtr=(StringPtr)adir->dr.d_name;
  419.     cinfo.hFileInfo.ioFDirIndex=adir->voffset++;
  420.     cinfo.hFileInfo.ioDirID=adir->dirid;
  421.     os=PBGetCatInfo(&cinfo,FALSE);
  422.     if(os!=0) {
  423.         errno=ENOENT;
  424.         return 0L;
  425.     }
  426.     PtoCstr((unsigned char *)adir->dr.d_name);
  427.     return &adir->dr;
  428. }
  429.  
  430.  
  431. /*
  432.  * close a directory file
  433.  */
  434. int closedir(DIR_pt adir)
  435. {
  436.     if(adir==0)return -1;
  437.     free(adir);
  438.     return 0;
  439. }
  440.  
  441.